﻿using System.Security.Principal;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;

namespace Web.Infrastructure.Security
{
    /// <summary>
    /// Authorization attribute created specifically for the administrative suite and forces users
    /// to go through the admin login page instead of the default one.
    /// </summary>
    public sealed class AdminAuthorizationAttribute : AuthorizeAttribute
    {
        /// <summary>
        /// Extracts identity required for authorization from the specified context.
        /// </summary>
        /// <param name="httpContext">The HTTP context to get requierd identity from.</param>
        protected IIdentity ExtractIdentity(HttpContextBase httpContext)
        {
            MultilevelPrincipal principal = httpContext.User as MultilevelPrincipal;
            if (null == principal)
                return null;

            return principal.AdministratorIdentity;
        }

        /// <summary>
        /// Called when a process requests authorization.
        /// </summary>
        /// <param name="filterContext">
        /// The filter context, which encapsulates information for using
        /// <see cref="T:System.Web.Mvc.AuthorizeAttribute"/>.
        /// </param>
        /// <exception cref="T:System.ArgumentNullException">
        /// The <paramref name="filterContext"/> parameter is <see langword="null"/>.
        /// </exception>
        public override void OnAuthorization(AuthorizationContext filterContext)
        {
            base.OnAuthorization(filterContext);

            if (!(filterContext.Result is HttpUnauthorizedResult))
                return;

            var route = new RouteValueDictionary
                {
                    { "controller", "Security" },
                    { "action", "LogOn" },
                    { "ReturnUrl", filterContext.HttpContext.Request.RawUrl }
                };

            filterContext.Result = new RedirectToRouteResult(route);
        }

        /// <summary>
        /// When overridden, provides an entry point for custom authorization checks.
        /// </summary>
        /// <param name="httpContext">
        /// The HTTP context, which encapsulates all HTTP-specific information about an individual HTTP
        /// request.
        /// </param>
        /// <returns>true if the user is authorized; otherwise, <see langword="false"/>.</returns>
        /// <exception cref="T:System.ArgumentNullException">
        /// The <paramref name="httpContext"/> parameter is <see langword="null"/>.</exception>
        protected override bool AuthorizeCore(HttpContextBase httpContext)
        {
            IIdentity identity = ExtractIdentity(httpContext);
            if (null == identity)
                return false;

            return identity.IsAuthenticated;
        }
    }
}